package com.whj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whj.domain.constants.SystemConstants;
import com.whj.domain.entity.Menu;
import com.whj.domain.enums.AppHttpCodeEnum;
import com.whj.domain.response.ResponseResult;
import com.whj.domain.vo.AddMenuVO;
import com.whj.mapper.MenuMapper;
import com.whj.service.MenuService;
import com.whj.utils.BeanCopyUtils;
import com.whj.utils.SecurityUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单权限表(Menu)表服务实现类
 *
 * @author wanghaijun
 * @since 2023-05-30 14:46:29
 */
@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Override
    public List<String> selectPermsByUserId(Long userId) {

        //如果用户id为1 代表管理员，返回所有权限
        if (SecurityUtils.isAdmin()) {
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回 该用户所具有的权限
        List<String> perms = menuMapper.selectPermsByUserId(userId);

        return perms;
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        MenuMapper menuMapper = getBaseMapper();
        List<Menu> menus = null;
        //判断是否是管理员
        if (SecurityUtils.isAdmin()) {
            //如果是 获取所有符合要求的Menu
            menus = menuMapper.selectAllRouterMenu();
        } else {
            //否则  获取当前用户所具有的Menu
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
        }
        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<Menu> menuTree = builderMenuTree(menus, 0L);
        return menuTree;
    }

    /**
     * 针对菜单名进行模糊查询
     * 针对菜单的状态进行查询。
     * 菜单要按照父菜单id和orderNum进行排序
     *
     * @param status
     * @param menuName
     * @return
     */
    @Override
    public ResponseResult listByStatus(String status, String menuName) {

        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(status), Menu::getStatus, status);
        queryWrapper.like(StringUtils.hasText(menuName), Menu::getMenuName, menuName);
        queryWrapper.orderByAsc(Menu::getOrderNum, Menu::getParentId);
        List<Menu> menuList = list(queryWrapper);
        return ResponseResult.okResult(menuList);
    }

    /**
     * 新增菜单
     *
     * @param menu
     * @return
     */
    @Override
    public ResponseResult addMenu(Menu menu) {
        menuMapper.insert(menu);
        return ResponseResult.okResult();
    }

    /**
     * 查询菜单通过id
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult<Menu> menuById(Long id) {
        Menu menu = menuMapper.selectById(id);
        return ResponseResult.okResult(menu);
    }

    /**
     * 修改菜单信息
     *
     * @param menu
     * @return
     */
    @Override
    public ResponseResult updateMenu(Menu menu) {
        Long parentId = menu.getParentId();
        if (menu.getId().equals(SystemConstants.Menu_Limit)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "不能设置为当前菜单");
        }
        if (menu.getId().equals(parentId)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "当前菜单不能和原来菜单相同");
        }
        menuMapper.updateById(menu);
        return ResponseResult.okResult();
    }


    /**
     * 删除菜单
     *
     * @param id
     * @return
     */
    @Override
    public ResponseResult deleteMenu(Long id) {
        Menu menu = menuMapper.selectById(id);
        if (menu.getParentId().equals(SystemConstants.Menu_Limit)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NOT_ALLOW, "不允许删除此菜单");
        }
        menuMapper.deleteById(id);
        return ResponseResult.okResult();
    }

    /**
     * 返回所有菜单的层级
     *
     * @return
     */
    @Override
    public List<AddMenuVO> treeSelect() {
        // 查询 所有菜单信息
        List<AddMenuVO> list = menuMapper.selectListAll();
        List<AddMenuVO> menuList = builderMenuTreeIter(list, 0l);
        return menuList;
    }

    /**
     * 通过id 查询当前菜单所拥有的权限
     * @param id
     * @return
     */
    @Override
    public List<String> selectMenuIdById(Long id) {
        List<String> menuIds=menuMapper.selectMenuIdById(id);
        return menuIds;
    }

    private List<AddMenuVO> builderMenuTreeIter(List<AddMenuVO> menus, long parenId) {
        List<AddMenuVO> listVO = new ArrayList<>();
        for (AddMenuVO menu : menus) {
            if (menu.getParentId().equals(parenId)){
               menu.setChildren(getChildrenIter(menu, menus));
               listVO.add(menu);
            }
        }
        return listVO;
    }

    private List<AddMenuVO> getChildrenIter(AddMenuVO menu, List<AddMenuVO> menus) {
        List<AddMenuVO> childrenList = new ArrayList<>();
        for (AddMenuVO m : menus) {
            if (m.getParentId().equals(menu.getId())){
                m.setChildren(getChildrenIter(m,menus));
                childrenList.add(m);
            }
        }
        return childrenList;
    }

    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     *
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}
